var TMP_USER_STR_COOKIE_KEY = "binance_tmp_user_str" // COOKIE中存储user_str值的key
var TME_USER_TAGS_KEY = "binance_tmp_user_tags" // COOKIE中存储临时用户（为登录用户）极光相关信息的key
var LOGIN_USER_TAGS_KEY_PREFIX = "logintags"
var LOGIN_USER_ALIAS_KEY = "loginalias"
var WEB_SIGNATURE_KEY_PREFIX = "usersignature"

if (!String.prototype.trim) {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/gm, '')
    }
}

function JpushSet(items) {
    this.items = items || []
    this.keys = {}
}

JpushSet.prototype = {
    add: function (value) {
        if (value instanceof Array) {
            var self = this
            for (var i = 0; i < value.length; i++) {
                self.add(value[i])
            }
        } else if (value instanceof JpushSet) {
            this.add(value.items)
        } else {
            var v = this.keys[value]
            if ((typeof v) == "undefined") {
                this.items.push(value)
                this.keys[value] = null
            }
        }
    },
    remove: function (value) {
        var v = this.keys[value]
        if ((typeof v) != "undefined") {
            delete this.keys[value]
            var index = this.items.indexOf(value)
            if (index != -1) {
                this.items.splice(index, 1)
            }
        }
    },
    contains: function (value) {
        return (typeof this.keys[value]) != "undefined"
    },
    size: function () {
        return this.items.length
    },
    forEach: function (callback) {
        var size = this.size()
        for (var i = 0; i < this.size(); i++) {
            try {
                callback(this.items[i])
            } finally {
                if (size > this.size()) {
                    //说明元素被删除
                    i--
                }
            }
        }
    },
    toString: function () {
        this.items.sort(function (a, b) {
            return a > b ? 1 : -1
        })
        return this.items.join(",")
    }
}

function JPushHelper() {
}

JPushHelper.prototype = {
    doGetWegSignatrue: function (callback) {
        this._getWegSignatrue = callback
        return this;
    },
    doGetLoginUserId: function (callback) {
        this._getLoginUserId = callback
        return this;
    },
    doSetAliasAndTags: function (callback) {
        this._setAliasAndTags = callback
        return this;
    },
    onMsgReceive: function (callback) {
        this._msgRecevie = callback
        return this;
    },
    doGetLanguage: function (callback) {
        this._getLanguage = callback
        return this;
    },
    start: function () {
        if (this._getWegSignatrue && this._setAliasAndTags) {
            if (!this._getLanguage) {
                this._getLanguage = function () {
                }
            }
            if (!this._getLoginUserId) {
                this._getLoginUserId = function () {
                }
            }
            if (!this._msgRecevie) {
                this._msgRecevie = function () {
                }
            }
            this.__initSdk()
            this.__monitorLogin()
        } else {
            throw new Error("You must invoke doGetWegSignatrue and doSetAliasAndTags first")
        }
    },
    __getCookie: function (key) {
        var cookies = window.top.document.cookie
        if (cookies) {
            cookies = cookies.split(";")
            for (var i = 0; i < cookies.length; i++) {
                var item = cookies[i]
                var arr = item.split("=")
                if (arr[0].trim() == key) {
                    return arr[1]
                }
            }
        }
        return null
    },
    /**
     * 添加cookie
     *
     * @param key
     * @param value
     * @param seconds
     *            有效期，单位秒，小于0无限期（100年），0session期限，大于0未来秒数期限
     */
    __addCookie: function (key, value, seconds) {
        var cookies = key + "=" + value
        seconds = seconds || 0
        if (seconds != 0) {
            var d = new Date()
            if (seconds < 0) {
                d.setFullYear(d.getFullYear() + 100)
            } else {
                d.setTime(d.getTime() + seconds * 1000)
            }
            cookies += ";expires=" + d.toString()
        }
        window.top.document.cookie = cookies
    },
    __removeCookie: function (key) {
        var d = new Date()
        d.setTime(d.getTime() - 10000)
        window.top.document.cookie = key + "=0;expires=" + d.toString()
    },
    __monitorLogin: function () {
        var self = this
        var monitorId = setInterval(function () {
            if (self.__getLoginUserId()) {
                clearInterval(monitorId)
                self.__initSdk()
                self.__monitorLogout()
            }
        }, 1000)
    },
    __monitorLogout: function () {
        var self = this
        var monitorId = setInterval(function () {
            if (!self.__getLoginUserId()) {
                clearInterval(monitorId)
                self.__initSdk()
                self.__monitorLogin()
            }
        }, 1500)
    },
    __monitorLanguageChange: function () {
        var self = this
        setTimeout(function () {
            var prevLanguage = self.__getOldLanguage()
            var curLanguage = self.__getlanguage()
            if (curLanguage != prevLanguage) {
                if (curLanguage) {
                    self.__setAliasAndTags(self.getRegid(), curLanguage, prevLanguage, true, function (status, data) {
                        self.__monitorLanguageChange()
                    })
                } else {
                    self.__monitorLanguageChange()
                }
            } else {
                self.__monitorLanguageChange()
            }
        }, 2000)
    },
    __nvl: function (value, defaultValue) {
        if (value == null || value == "undefined" || value == "null") {
            return defaultValue
        }
        return value
    },
    __getLoginUserId: function () {
        return this.__nvl(this._getLoginUserId(), "")
    },
    __getWegSignature: function (force, callback) {
        var loginUserId = this.__getLoginUserId(), userStr = loginUserId
        if (!userStr) {
            // 未登录，则是临时用户，从cookie中拿缓存的userStr
            userStr = this.__getCookie(TMP_USER_STR_COOKIE_KEY)
        }
        userStr = this.__nvl(userStr, "")
        var signature = this.__getCookie(WEB_SIGNATURE_KEY_PREFIX + userStr)
        if (force !== true && signature) {
            //cookie中存在有效的签名信息，且不强制重新从服务器端获取签名所需信息
            callback(JSON.parse(signature))
        } else {
            var self = this
            this._getWegSignatrue(userStr, function (signature) {
                userStr = signature.user_str
                //将签名信息存入cookie中，有效期40分钟（该有效期必须小于后端设置的签名有效期，目前后端设置的签名有效期是1小时）
                self.__addCookie(WEB_SIGNATURE_KEY_PREFIX + userStr, JSON.stringify(signature), 2400)
                if (!loginUserId) {
                    // 未登录，则需要将临时用户userStr存入cookie
                    self.__addCookie(TMP_USER_STR_COOKIE_KEY, userStr, -1)
                }
                callback(signature)
            })
        }
    },
    __getlanguage: function () {
        var code = this.__nvl(this._getLanguage(), "")
        if (code) {
            return this.languagePrefix + code
        }
        return ""
    },
    getRegid: function () {
        return this.reg_id
    },
    /**
     * 设置标签
     * @param tagsToAdd
     * @param tagsToRemove
     */
    setTags: function (tagsToAdd, tagsToRemove, callback) {
        callback = callback || function () {
        }
        this.__setAliasAndTags(this.getRegid(), tagsToAdd, tagsToRemove, true, callback)
    },
    __setAliasAndTags: function (regid, tagsToAdd, tagsToRemove, force, callback) {
        if (regid == null) {
            try {
                callback("error")
            } finally {
                return
            }
        }
        alias = this.__getLoginUserId()
        if (!(tagsToAdd instanceof JpushSet)) {
            if (tagsToAdd != null && (typeof tagsToAdd) == "string" && tagsToAdd.trim().length > 0) {
                tagsToAdd = new JpushSet(tagsToAdd.split(","))
            } else {
                tagsToAdd = new JpushSet()
            }
        }
        if (!(tagsToRemove instanceof JpushSet)) {
            if (tagsToRemove != null && (typeof tagsToRemove) == "string" && tagsToRemove.trim().length > 0) {
                tagsToRemove = new JpushSet(tagsToRemove.split(","))
            } else {
                tagsToRemove = new JpushSet()
            }
        }
        if (this.__getLoginUserId()) {
            //已登录
            var tags = this.__getCookie(LOGIN_USER_TAGS_KEY_PREFIX + regid) || ""
            if (tagsToAdd.size() == 0 && tagsToRemove.size() == 0) {
                var alias = this.__getCookie(LOGIN_USER_ALIAS_KEY + alias)
                if (!alias) {
                    var self = this
                    this.__setAlias(alias, function (status, respData) {
                        if (status === "success") {
                            self.__addCookie(LOGIN_USER_ALIAS_KEY + alias, 0, 30 * 24 * 3600)
                            callback("success", tags)
                        } else {
                            callback(status)
                        }
                    })
                } else {
                    callback("success", tags)
                }
            } else {
                var lastest = this.__getCookie(LOGIN_USER_TAGS_KEY_PREFIX + regid + "lastest") || 0,
                    now = new Date().getTime()
                var expire = 30 * 24 * 3600 //30天
                //如果要强制调用后端或缓存中不存在标签或者与最近一次调用后台的时间间隔大于30天，则允调用后台进行设置
                //此处的目的主要是为了减少用户登录时访问后台的频率，因为用户登录时只会设置语言标签和别名
                //如果用户第一次登录或距离第一次登录时间间隔大于30天则肯定会调用后端
                //当用户语言真正变化的时候系统会自动检测到，从而强制调用后端
                if (force === true || !tags || now - lastest > expire * 1000) {
                    var self = this
                    this._setAliasAndTags(regid, alias, tagsToAdd.toString(), tagsToRemove.toString(), function (success, tags) {
                        if (success === true) {
                            if (tags && tags.length > 0) {
                                tags = tags.join(",")
                                self.__addCookie(LOGIN_USER_TAGS_KEY_PREFIX + regid, tags, -1)
                                self.__addCookie(LOGIN_USER_TAGS_KEY_PREFIX + regid + "lastest", now, -1)
                                callback("success", tags)
                            }
                        } else {
                            callback("error")
                        }
                    })
                } else {
                    callback("success", tags)
                }
            }
        } else {
            //未登录
            var self = this
            var oldTags = this.__getCookie(TME_USER_TAGS_KEY) || ""
            var newTags = new JpushSet()
            newTags.add(tagsToAdd)
            if (oldTags) {
                newTags.add(oldTags.split(","))
            }
            var flag = false
            newTags.forEach(function (tag) {
                if (tag.indexOf(self.languagePrefix) == 0) {
                    if (flag) {
                        newTags.remove(tag)
                    } else {
                        flag = true
                    }
                }
            })
            tagsToRemove.forEach(function (tag) {
                newTags.remove(tag)
            })
            var tags = newTags.toString()
            window.top.jpushClient.setTags({
                'tags': tags
            }).onSuccess(function (data) {
                self.__addCookie(TME_USER_TAGS_KEY, tags, -1)
                callback("success", tags)
            }).onFail(function (data) {
                callback("error")
            }).onTimeout(function (data) {
                callback("timeout")
            })
        }
    },
    __setAlias: function (alias, callback) {
        if (window.top.jpushClient) {
            window.top.jpushClient.setAlias({
                'alias': alias
            }).onSuccess(function (data) {
                if (callback) {
                    callback("success")
                }
            }).onFail(function (data) {
                if (callback) {
                    callback("error")
                }
            }).onTimeout(function (data) {
                if (callback) {
                    callback("timeout")
                }
            })
        } else {
            if (callback) {
                callback("error")
            }
        }
    },
    __getOldLanguage: function () {
        var tags = this.__getCookie(LOGIN_USER_TAGS_KEY_PREFIX + this.getRegid()) || ""
        if (tags) {
            var arr = tags.split(",")
            for (var i = 0; i < arr.length; i++) {
                var tag = arr[i]
                if (tag.indexOf(this.languagePrefix) == 0) {
                    return tag
                }
            }
        }
        return ""
    },
    __initSdk: function (force) {
        /* try {
             window.top.jpushClient.channel.client.close()
         } catch (e) {
         }*/
        var self = this
        this.__getWegSignature(force, function (signature) {
            self.languagePrefix = self.__nvl(signature.languagePrefix, "")
            self.globalTags = self.__nvl(signature.globalTags, "")
            if (!window.top.jpushClient) {
                window.top.jpushClient = new JPush({
                    'address': signature.wsAddress,
                    'debug': signature.debug
                })
            }
            window.top.jpushClient.init({
                'user_str': signature.user_str,
                'signature': signature.signature,
                'appkey': signature.appkey,
                'timestamp': signature.timestamp,
                'random_str': signature.random_str
            }).onSuccess(function (data) {
                self.__initSdkOnSuccess(data)
                window.top.jpushClient.onMsgReceive(function (data) {
                    self._msgRecevie(data)
                })
            }).onFail(function (data) {
                //判断失败原因，如果是签名过期，则重新获取签名然后初始化
                if (data.code == 4003) {
                    self.__initSdk(true)
                }
            })
        })
    },
    __initSdkOnSuccess: function (jsonData) {
        this.reg_id = jsonData.regid
        var tagsToAdd = new JpushSet()
        var language = this.__getlanguage()
        if (language) {
            tagsToAdd.add(language)
        }
        if (this.globalTags) {
            tagsToAdd.add(this.globalTags)
        }
        var self = this
        this.__setAliasAndTags(jsonData.regid, tagsToAdd, null, false, function (status) {
            if (status === "success") {
                self.__monitorLanguageChange()
            }
        })
    }
}